package com.zjs.fifter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import pojo.ResultStatus;
import pojo.TokenUtils;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class GatewayFilter implements GlobalFilter, Ordered {
    @Autowired
    RedisTemplate redisTemplate;

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String url = request.getURI().getRawPath();
        log.info("url:"+url);
        if (url.contains("/login")){
            return chain.filter(exchange);
        }
        String token = request.getHeaders().getFirst("token");
        if (token==null){
            return tokenErrror(response);
        }
        TokenUtils tokenUtils = TokenUtils.token().setKey("123456");
        Integer res = tokenUtils.parseToken(token);
//        if(!TokenUtils.SUCCESS.equals(res)) {
//            if(!TokenUtils.ERROR_EXPIRE.equals(res)) {
//                return tokenErrror(response);
//            }
//        }
        if(TokenUtils.ERROR_SIGN.equals(res) || TokenUtils.ERROR.equals(res)) {
            return tokenErrror(response);
        }

        String userId = tokenUtils.getClaim("userId");
        String key = "pc:"+userId;

        if(!redisTemplate.hasKey(key)) {
            return tokenErrror(response);
        }

        // token刷新
        String userName = tokenUtils.getClaim("userName");
        String newToken = TokenUtils.token()
                .setKey("123456")
                .setExpire(60 * 30)
                .createToken("userId", userId, "userName", userName);
        redisTemplate.opsForValue().set(token, newToken, 30, TimeUnit.MINUTES);
        redisTemplate.expire(key, 30, TimeUnit.MINUTES);

        return chain.filter(exchange);
    }

    private Mono<Void> tokenErrror(ServerHttpResponse response) throws JsonProcessingException {
        // 解决乱码
        HttpHeaders headers = response.getHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 添加错误信息
        ResultStatus resultResponse = ResultStatus.FTLED(401, "token错误");

        ObjectMapper objectMapper = new ObjectMapper();
        String err = objectMapper.writeValueAsString(resultResponse);

        DataBuffer wrap = response.bufferFactory().wrap(err.getBytes(StandardCharsets.UTF_8));

        // 返回错误信息
        return response.writeWith(Mono.just(wrap));
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
